package gouhuo.allbugs.top.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import gouhuo.allbugs.top.common.BaseResponse;
import gouhuo.allbugs.top.common.BusinessException;
import gouhuo.allbugs.top.common.ErrorCode;
import gouhuo.allbugs.top.constant.RedisConstants;
import gouhuo.allbugs.top.model.domain.User;
import gouhuo.allbugs.top.model.request.user.UserLoginRequest;
import gouhuo.allbugs.top.model.request.user.UserRegisterRequest;
import gouhuo.allbugs.top.model.request.user.UserSpeakRequest;
import gouhuo.allbugs.top.model.vo.UserVO;
import gouhuo.allbugs.top.service.FriendsService;
import gouhuo.allbugs.top.service.UserService;
import gouhuo.allbugs.top.utils.DESUtil;
import gouhuo.allbugs.top.utils.QiNiuUtil;
import gouhuo.allbugs.top.utils.ResultUtil;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 用户
 */

@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private FriendsService friendsService;

    @Resource
    private QiNiuUtil qiNiuUtil;

    private LineCaptcha lineCaptcha;

    @ApiOperation("获取七牛云的Token")
    @GetMapping("/token")
    public BaseResponse<String> getToken() {
        return ResultUtil.success(qiNiuUtil.getToken());
    }

    @ApiOperation("上传到七牛云并返回外链")
    @PostMapping("/upload")
    public BaseResponse<String> upLoadImg(@RequestParam("data") MultipartFile data, HttpServletRequest request) {
        if (data.isEmpty()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        try {
            boolean saveImage = qiNiuUtil.saveImage(data, request);
            if (!saveImage) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "上传成功但插入数据库失败");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ResultUtil.success("上传成功");
    }

    @ApiOperation("发送验证码")
    @PostMapping("/code")
    public BaseResponse<String> sendCode(@RequestParam("phone") String phone) {
        if (phone == null || phone.length() != 11) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        String cacheCode = stringRedisTemplate.opsForValue().get(RedisConstants.LOGIN_CODE_KEY + phone);
        if (cacheCode != null) {
            stringRedisTemplate.expire(RedisConstants.LOGIN_CODE_KEY + phone, RedisConstants.LOGIN_CODE_TTL, TimeUnit.MINUTES);
            return ResultUtil.success(cacheCode);
        }
        String code = RandomUtil.randomNumbers(4);
        stringRedisTemplate.opsForValue().set(RedisConstants.LOGIN_CODE_KEY + phone, code, RedisConstants.LOGIN_CODE_TTL, TimeUnit.MINUTES);
        return ResultUtil.success(code);
    }

    @ApiOperation("获取图片验证码")
    @GetMapping("/getImgCode")
    public void getImgCode(HttpServletResponse response) {
        RandomGenerator randomGenerator = new RandomGenerator("0123456789", 4);
        // 定义图片的显示大小
        lineCaptcha = CaptchaUtil.createLineCaptcha(100, 30);
        response.setContentType("image/jpeg");
        response.setHeader("Pragma", "No-cache");
        try {
            // 调用父类的 setGenerator() 方法，设置验证码的类型
            lineCaptcha.setGenerator(randomGenerator);
            // 输出到页面
            lineCaptcha.write(response.getOutputStream());
            // 关闭流
            response.getOutputStream().close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @ApiOperation("注册")
    @PostMapping("/register")
    public BaseResponse<Long> userRegister(@RequestBody UserRegisterRequest userRegisterRequest) {
        if (userRegisterRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        String phone = userRegisterRequest.getPhone();
        String userPassword = userRegisterRequest.getUserPassword();
        String checkPassword = userRegisterRequest.getCheckPassword();
        String userName = userRegisterRequest.getUserName();
        String email = userRegisterRequest.getEmail();
        Integer gender = userRegisterRequest.getGender();
        if (StrUtil.isAllNotBlank(phone, userPassword, checkPassword, userName, email) || gender == null) {
            long result = userService.userRegister(phone, userPassword, checkPassword, userName, email, gender);
            return ResultUtil.success(result);
        }
        throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }

    @ApiOperation("登录")
    @PostMapping("/login")
    public BaseResponse userLogin(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request, HttpServletResponse response) {
        if (userLoginRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        String phone = userLoginRequest.getPhone();
        String userPassword = userLoginRequest.getUserPassword();
        String userCode = userLoginRequest.getUserCode();
        Integer remember = userLoginRequest.getRemember();
        if (phone == null || remember == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        UserVO userVO = userService.userLogin(phone, userPassword, userCode, remember, 0, request, response);
        if (userVO == null) {
            return ResultUtil.error(userCode == null ? "密码错误" : "验证码错误");
        }
        if (userVO.getId() == null) {
            throw new BusinessException(ErrorCode.NO_REG);
        }
        return ResultUtil.success(userVO);
    }

    @ApiOperation("登出")
    @GetMapping("/logout")
    public BaseResponse<Boolean> userLogout(@RequestParam("userId") Long userId, HttpServletRequest request, HttpServletResponse response, @CookieValue(value = "loginCookie", defaultValue = "") String cookie) {
        if (userId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        return ResultUtil.success(userService.userLogout(userId, request, response, cookie));
    }

    @ApiOperation("获取当前用户")
    @GetMapping("/current")
    public BaseResponse<UserVO> getCurrentUser(HttpServletRequest request, HttpServletResponse response, @CookieValue(value = "loginCookie", defaultValue = "") String cookie) {
        UserVO userVO = userService.getLoginUser(request, true);
        if (userVO.getId() == null) {
            //利用cookie完成登录
            if (StrUtil.isNotBlank(cookie)) {
                String decrypt = DESUtil.decrypt(cookie);
                int userId = Integer.parseInt(decrypt.split("_")[1]);
                return ResultUtil.success(userService.userLogin(null, null, null, 0, userId, request, response));
            }
            //没有cookie，未登录
            throw new BusinessException(ErrorCode.NOT_LOGIN);
        }
        return ResultUtil.success(userVO);
    }

    @ApiOperation("根据id获取用户")
    @GetMapping("/other")
    public BaseResponse<UserVO> getOtherUser(@RequestParam("otherUserId") Long otherUserId) {
        if (otherUserId == null || otherUserId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User user = userService.getById(otherUserId);
        if (user == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }
        return ResultUtil.success(BeanUtil.copyProperties(user, UserVO.class));
    }

    @ApiOperation("用户反馈")
    @PostMapping("/speak")
    public BaseResponse<String> fromUserSpeak(@RequestBody UserSpeakRequest userSpeakRequest, HttpServletRequest request) {
        if (userSpeakRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        UserVO userVO = userService.getLoginUser(request, null);
        Integer star = userSpeakRequest.getStar();
        String speak = userSpeakRequest.getSpeak();
        boolean b = userService.fromUserSpeak(userVO, star, speak);
        if (b) {
            return ResultUtil.success("反馈成功");
        }
        throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }

    @ApiOperation("根据昵称搜索")
    @GetMapping("/search")
    public BaseResponse<List<UserVO>> searchUsers(@RequestParam("searchMessage") String searchMessage) {
        if (StrUtil.isBlank(searchMessage)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        return ResultUtil.success(userService.searchUsers(searchMessage));
    }

    @ApiOperation("根据标签搜索-未实现")
    @GetMapping("/search/tags")
    public BaseResponse<List<UserVO>> searchUsersByTags(@RequestParam(required = false) List<String> tagNameList) {
        if (CollectionUtils.isEmpty(tagNameList)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        List<UserVO> userList = userService.searchUsersByTags(tagNameList);
        return ResultUtil.success(userList);
    }

    @ApiOperation("修改用户信息")
    @PostMapping("/update")
    public BaseResponse<String> updateUser(@RequestBody User user, HttpServletRequest request) {
        if (user == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        UserVO userVO = userService.getLoginUser(request, null);
        boolean update = userService.updateUser(user, userVO, request);
        if (!update) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "旧密码错误");
        }
        return ResultUtil.success("修改成功");
    }

    @ApiOperation("删除用户-未实现")
    @PostMapping("/delete")
    public BaseResponse<Boolean> deleteUser(@RequestBody long id, HttpServletRequest request) {
        if (!userService.isAdmin(request)) {
            throw new BusinessException(ErrorCode.NO_AUTH);
        }
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        boolean b = userService.removeById(id);
        return ResultUtil.success(b);
    }

    @ApiOperation("获取所有好友的id列表")
    @GetMapping("/myFriendId")
    public BaseResponse<List<Long>> getMyFriendId(@RequestParam("userId") Long userId) {
        if (userId == null || userId == 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        return ResultUtil.success(friendsService.getMyFriendId(userId));
    }

    @ApiOperation("普通模式下的用户列表")
    @GetMapping("/list")
    public BaseResponse<List<User>> listUsers(long pageNum, long pageSize) {
        ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
        List<User> userPage = (List<User>) valueOperations.get(RedisConstants.USER_LIST_KEY);
        if (userPage != null) {
            return ResultUtil.success(userPage);
        }
        userPage = userService.list();
        if (userPage == null) {
            return null;
        }
        // 写缓存
        valueOperations.set(RedisConstants.USER_LIST_KEY, userPage, RedisConstants.USER_LIST_TTL, TimeUnit.MINUTES);
        return ResultUtil.success(userPage);
    }

    @ApiOperation("心动模式下的用户列表")
    @GetMapping("/match")
    public BaseResponse<List<UserVO>> matchUsers(long num, HttpServletRequest request) {
        if (num <= 0 || num > 20) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        UserVO userVO = userService.getLoginUser(request, null);
        return ResultUtil.success(userService.matchUsers(num, userVO));
    }
}